package org.study.bookmanager.service.impl;

import jakarta.annotation.Resource;
import jakarta.persistence.criteria.Predicate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.study.bookmanager.entity.*;
import org.study.bookmanager.io.reponse.RestBean;
import org.study.bookmanager.io.request.Borrow.AddBorrowReq;
import org.study.bookmanager.io.request.PageReq;
import org.study.bookmanager.repo.*;
import org.study.bookmanager.service.BorrowService;
import org.study.bookmanager.service.ReservationService;
import org.study.bookmanager.utils.DateUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;


@Service
public class ReservationServiceImpl implements ReservationService {
    @Resource
    ReservationRespository reservationRespository;

    @Resource
    BooksRespository booksRespository;

    @Resource
    UsersRespository usersRespository;

    @Resource
    BorrowService borrowService;

    @Value("${book-manager.default.duedate}")
    int dueDate;

    /**
     * @param userDetails
     * @param bookId
     * @return
     */
    @Override
    public Object addReservation(UserDetails userDetails, int bookId) {
        if(!booksRespository.existsById(bookId)){
            return RestBean.Code.图书信息不存在;
        }
        Optional<Books> book=booksRespository.findById(bookId);
        Users user=usersRespository.findByuserName(userDetails.getUsername());
        if(book.isPresent()){
            Books books=book.get();
            Reservation reservation=Reservation.builder().
                    user(user).
                    book(books).build();
            AddBorrowReq req=new AddBorrowReq();
            req.setBook_id(bookId);
            req.setDue_date(DateUtils.addDays(new Date(),dueDate));
            if(borrowService.addBorrow(userDetails,req) instanceof RestBean.Code code){
                return code;
            }else{
                reservation.setFinish(true);
            }
            booksRespository.save(books);
            reservationRespository.save(reservation);
            return RestBean.ok;
        }else{
            return RestBean.Code.服务错误;
        }
    }

    /**
     * @param Id
     * @return
     */
    @Override
    public Object deleteReservation(UserDetails userDetails,int Id) {
        Users users=usersRespository.findByuserName(userDetails.getUsername());
        if(!reservationRespository.existsById(Id)){
            return RestBean.Code.借阅记录不存在;
        }
        if(!reservationRespository.existsReservationByUserAndFinishIsFalseAndReservationID(users,Id)){
            return RestBean.Code.预约已完成;
        }
        reservationRespository.deleteById(Id);
        return RestBean.ok;
    }

    /**
     * @param userDetails
     * @param pageReq
     * @return
     */
    @Override
    public Object getReservations(UserDetails userDetails, PageReq pageReq) {
        Pageable pageable = PageRequest.of(pageReq.getPage(), pageReq.getLimit());

        Specification<Reservation> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            Users user = usersRespository.findByuserName(userDetails.getUsername());
            if (user != null) {
                predicates.add(criteriaBuilder.equal(root.get("users"), user));
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        return reservationRespository.findAll(specification, pageable);
    }
}
